---
title: Next.js Pages Router
---

import { Callout } from 'nextra-theme-docs';

# Next.js Pages Router

<Callout>
  The Next.js Pages Router's API Routes **do not** support streaming responses.
  You can use the `pages/` directory for the frontend while using an `app/`
  directory Route Handler for handling your LLM responses with streaming.

See how to use a Route Handler [here](https://sdk.vercel.ai/docs/guides/frameworks/nextjs-app#route-handlers).

</Callout>

## API routes

### Edge Runtime

The Edge Runtime supports the same Response types as in the App Router, so the code is equivalent between the two.

```typescript
import { OpenAIStream, StreamingTextResponse } from 'ai';
import OpenAI from 'openai';

// Create an OpenAI API client (that's edge friendly!)
const openai = new OpenAI({
  apiKey: process.env.OPENAI_API_KEY || '',
});

// IMPORTANT! Set the runtime to edge
export const runtime = 'edge';

export default async function handler(req: Request, res: Response) {
  const { messages } = await req.json();

  // Ask OpenAI for a streaming chat completion given the prompt
  const response = await openai.chat.completions.create({
    model: 'gpt-3.5-turbo',
    stream: true,
    messages,
  });

  // Convert the response into a friendly text-stream
  const stream = OpenAIStream(response);
  // Respond with the stream
  return new StreamingTextResponse(stream);
}
```

### Node.js Runtime

Node.js offers different Request and Response types compared to the Edge Runtime and App Router, so we need to use the `streamToResponse` helper function
in place of `StreamingTextResponse`.

```typescript
import { OpenAIStream, StreamingTextResponse, streamToResponse } from 'ai';
import { NextApiRequest, NextApiResponse } from 'next';
import OpenAI from 'openai';

// Create an OpenAI API client (that's edge friendly!)
const openai = new OpenAI({
  apiKey: process.env.OPENAI_API_KEY || '',
});

export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse,
) {
  const { messages } = await req.body;

  // Ask OpenAI for a streaming chat completion given the prompt
  const response = await openai.chat.completions.create({
    model: 'gpt-3.5-turbo',
    stream: true,
    messages,
  });

  // Convert the response into a friendly text-stream
  const stream = OpenAIStream(response);

  /**
   * Converts the stream to a Node.js Response-like object.
   * Please note that this sends the response as one message once it's done.
   */
  return streamToResponse(stream, res);
}
```

## Components

You can use the client `useChat` and `useCompletion` hooks the same between the Pages and App Router.

```jsx
import { useChat } from 'ai/react';

// Optional but recommended: use the Edge Runtime. This can only be done at the page level, not inside nested components.
export const runtime = 'edge';

export default function IndexPage() {
  const { messages, handleSubmit, input, handleInputChange } = useChat();

  return (
    <form onSubmit={handleSubmit}>
      <label for="input">Prompt</label>
      <input
        name="prompt"
        value={input}
        onChange={handleInputChange}
        id="input"
      />
      <button type="submit">Submit</button>
      {messages.map((message, i) => (
        <div key={i}>{message.content}</div>
      ))}
    </form>
  );
}
```
